-module(ptests).
-export([tests/1, fib/1]).

tests([N]) ->
    Nsched = list_to_integer(atom_to_list(N)),
    run_tests(1, Nsched).

run_tests(N, Nsched) ->
    case test(N) of
        stop ->
            init:stop();
        Val ->
            io:format("~p.~n", [{Nsched, Val}]),
            run_tests(N+1, Nsched)
    end.

test(1) ->
    % Make 100 lists
    % Each lists contain 1000 randon integers
    seed(),
    S = lists:seq(1, 100),
    L = lists:map(fun(_) -> mkList(1000) end, S),
    {Time1, S1} = timer:tc(lists, map, [fun lists:sort/1, L]),
    {Time2, S2} = timer:tc(pmap, pmap, [fun lists:sort/1, L]),
    {sort, Time1, Time2, equal(S1, S2)};
test(2) ->
    % L = [27, 27, 27,...] 100 times
    %L = lists:duplicate(100, 27),
    L = [27, 27],
    {Time1, S1} = timer:tc(lists, map, [fun ptests:fib/1, L]),
    {Time2, S2} = timer:tc(pmap, pmap, [fun ptests:fib/1, L]),
    {fib, Time1, Time2, equal(S1, S2)};
test(3) ->
    stop.

%% Equal is used to test that map and pmap compute the same thing
equal(S, S) -> true;
equal(S1, S2) -> {differ, S1, S2}.

%% recursive (ineffient) fibonacci
fib(0) -> 1;
fib(1) -> 1;
fib(N) -> fib(N-1) + fib(N-2).

%% Reset the random number generator. This is so we get the same
%% sequence of random numbers each time we run the program
seed() -> random:seed(44, 55, 66).

%% Make a list of K randon numbers
%% Each randon number in the ranget 1..1000000
mkList(K) -> mkList(K, []).

mkList(0, L) -> L;
mkList(N, L) -> mkList(N-1, [random:uniform(1000000)|L]).
